package cn.iocoder.yudao.framework.location;

import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.exception.KnownServiceException;
import cn.iocoder.yudao.framework.geo.GeoParser;
import cn.iocoder.yudao.framework.geo.GeoUtils;
import jakarta.annotation.Nonnull;
import lombok.extern.slf4j.Slf4j;

/**
 * <pre>
 * OOoO0OOoO0OOOooo0oOOOO0OOOOO0oooOO0ooOOO0Ooooo0OOOOo0ooooO0OOooo0Ooooo0OOOOO
 * 自研的根据经纬度获取行政区域，基于全中国的省市区边界数据研发。
 * 数据来源一：<a href="https://datav.aliyun.com/portal/school/atlas/area_selector">DataV.GeoAtlas 范围选择器</a>
 * 数据来源二：<a href="https://geojson.hxkj.vip">https://github.com/TangSY/echarts-map-demo</a>
 * 数据来源三：<a href="https://gitee.com/xiangyuecn/AreaCity-JsSpider-StatsGov">AreaCity-JsSpider-StatsGov</a>
 * OOoO0OOoO0OOOooo0oOOOO0OOOOO0oooOO0ooOOO0Ooooo0OOOOo0ooooO0OOooo0Ooooo0OOOOO
 * </pre>
 *
 * @author 山野羡民（1032694760@qq.com）
 * @since 2024/11/27
 */
@Slf4j
public class DefaultLocationClient implements LocationClient {

    @Nonnull
    @Override
    public LocationInfo getLocation(Double longitude, Double latitude) {
        try {
            GeoParser.Region province = GeoUtils.findProvince(longitude, latitude);
            String provinceName = province.getName();
            String provinceCode = province.getAdcode();
            GeoParser.Region city = GeoUtils.findCity(province.getAdcode(), longitude, latitude);
            String cityName = city.getName();
            String cityCode = city.getAdcode();
            if (StrUtil.isBlank(provinceCode)) {
                // 直辖市可能没有市级编码
                cityName = provinceName;
                cityCode = provinceCode;
            }
            GeoParser.Region county = GeoUtils.findCounty(province.getAdcode(), city.getAdcode(), longitude, latitude);
            String countyName = county.getName();
            String countyCode = county.getAdcode();
            LocationInfo respDTO = new LocationInfo();
            respDTO.setFormattedAddress(provinceName + cityName + countyName);
            respDTO.setProvinceName(provinceName);
            respDTO.setProvinceCode(provinceCode);
            respDTO.setCityName(cityName);
            respDTO.setCityCode(cityCode);
            respDTO.setCountyName(countyName);
            respDTO.setCountyCode(countyCode);
            return respDTO;
        } catch (Exception e) {
            log.warn("根据经纬度获取位置信息，GEO 数据处理出错", e);
            throw new KnownServiceException("根据经纬度获取位置信息失败：" + e.getMessage());
        }
    }

}
